From edae0c43d12f6fc4fc89db50651ed999d43ef5ce Mon Sep 17 00:00:00 2001 From: robertl Date: Tue, 26 Jul 2005 20:58:26 +0000 Subject: [PATCH] Olaf adds filtering for time ranges in new track filter and the 'move' suboption so that ranges can be time shifted. Makefile: regenerate. --- Makefile | 18 +- README | 37 ++- internal_styles.c | 3 +- pathaway.c | 6 +- trackfilter.c | 572 ++++++++++++++++++++++++++++++++++++---------- 5 files changed, 501 insertions(+), 135 deletions(-) diff --git a/Makefile b/Makefile index b36a46c41..60c1e494e 100644 --- a/Makefile +++ b/Makefile @@ -143,6 +143,7 @@ msvc-build: an1.o: an1.c defs.h queue.h gbtypes.h an1sym.h arcdist.o: arcdist.c defs.h queue.h gbtypes.h grtcirc.h +bcr.o: bcr.c defs.h queue.h gbtypes.h garmin_tables.h brauniger_iq.o: brauniger_iq.c defs.h queue.h gbtypes.h jeeps/gpsserial.h \ jeeps/gps.h jeeps/../defs.h jeeps/gpsport.h jeeps/gpsserial.h \ jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h \ @@ -153,8 +154,10 @@ cetus.o: cetus.c defs.h queue.h gbtypes.h coldsync/palm.h coldsync/pdb.h coastexp.o: coastexp.c defs.h queue.h gbtypes.h xmlgeneric.h uuid.h copilot.o: copilot.c defs.h queue.h gbtypes.h coldsync/palm.h \ coldsync/pdb.h -csv_util.o: csv_util.c defs.h queue.h gbtypes.h csv_util.h grtcirc.h strptime.h +csv_util.o: csv_util.c defs.h queue.h gbtypes.h csv_util.h grtcirc.h \ + strptime.h delgpl.o: delgpl.c defs.h queue.h gbtypes.h +dopfilt.o: dopfilt.c defs.h queue.h gbtypes.h duplicate.o: duplicate.c defs.h queue.h gbtypes.h easygps.o: easygps.c defs.h queue.h gbtypes.h filter_vecs.o: filter_vecs.c defs.h queue.h gbtypes.h @@ -166,6 +169,12 @@ garmin.o: garmin.c defs.h queue.h gbtypes.h jeeps/gps.h jeeps/../defs.h \ jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h garmin_tables.h garmin_tables.o: garmin_tables.c garmin_tables.h gcdb.o: gcdb.c defs.h queue.h gbtypes.h coldsync/palm.h coldsync/pdb.h +gdb.o: gdb.c defs.h queue.h gbtypes.h garmin_tables.h jeeps/gpsmath.h \ + jeeps/gps.h jeeps/../defs.h jeeps/gpsport.h jeeps/gpsserial.h \ + jeeps/gpssend.h jeeps/gpsread.h jeeps/gpsutil.h jeeps/gpsapp.h \ + jeeps/gpsprot.h jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmath.h \ + jeeps/gpsnmea.h jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h \ + jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h geo.o: geo.c defs.h queue.h gbtypes.h xmlgeneric.h geoniche.o: geoniche.c defs.h queue.h gbtypes.h coldsync/palm.h \ coldsync/pdb.h @@ -198,8 +207,6 @@ magproto.o: magproto.c defs.h queue.h gbtypes.h magellan.h main.o: main.c defs.h queue.h gbtypes.h mapsend.o: mapsend.c defs.h queue.h gbtypes.h mapsend.h magellan.h mapsource.o: mapsource.c defs.h queue.h gbtypes.h garmin_tables.h -gdb.o: gdb.c defs.h queue.h gbtypes.h garmin_tables.h \ - jeeps/gpsmath.h garmin_tables.h mkshort.o: mkshort.c defs.h queue.h gbtypes.h navicache.o: navicache.c defs.h queue.h gbtypes.h netstumbler.o: netstumbler.c defs.h queue.h gbtypes.h csv_util.h @@ -246,7 +253,7 @@ tpg.o: tpg.c defs.h queue.h gbtypes.h jeeps/gpsmath.h jeeps/gps.h \ jeeps/gpscom.h jeeps/gpsfmt.h jeeps/gpsmath.h jeeps/gpsnmea.h \ jeeps/gpsmem.h jeeps/gpsrqst.h jeeps/gpsinput.h jeeps/gpsproj.h \ jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h -trackfilter.o: trackfilter.c defs.h queue.h gbtypes.h +trackfilter.o: trackfilter.c defs.h queue.h gbtypes.h strptime.h util.o: util.c defs.h queue.h gbtypes.h util_crc.o: util_crc.c uuid.o: uuid.c uuid.h @@ -258,7 +265,6 @@ vcf.o: vcf.c defs.h queue.h gbtypes.h jeeps/gpsmath.h jeeps/gps.h \ jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h vecs.o: vecs.c defs.h queue.h gbtypes.h csv_util.h vitosmt.o: vitosmt.c defs.h queue.h gbtypes.h -bcr.o: defs.h queue.h gbtypes.h garmin_tables.h vmem.o: vmem.c defs.h queue.h gbtypes.h waypt.o: waypt.c defs.h queue.h gbtypes.h xcsv.o: xcsv.c defs.h queue.h gbtypes.h csv_util.h @@ -350,5 +356,5 @@ jeeps/gpsutil.o: jeeps/gpsutil.c jeeps/gps.h jeeps/../defs.h \ jeeps/gpsproj.h jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h shapelib/dbfopen.o: shapelib/dbfopen.c shapelib/shapefil.h shapelib/shpopen.o: shapelib/shpopen.c shapelib/shapefil.h -internal_styles.c: mkstyle.sh style/README.style style/arc.style style/csv.style style/custom.style style/dna.style style/fugawi.style style/gpsdrive.style style/gpsman.style style/mapconverter.style style/mxf.style style/nima.style style/s_and_t.style style/saplus.style style/tabsep.style style/xmap.style style/xmapwpt.style +internal_styles.c: mkstyle.sh style/README.style style/arc.style style/csv.style style/custom.style style/dna.style style/fugawi.style style/gpsdrive.style style/gpsdrivetrack.style style/gpsman.style style/mapconverter.style style/mxf.style style/nima.style style/openoffice.style style/s_and_t.style style/saplus.style style/tabsep.style style/xmap.style style/xmapwpt.style ./mkstyle.sh > internal_styles.c || (rm -f internal_styles.c ; exit 1) diff --git a/README b/README index ba814f9d7..1e6ac1a13 100644 --- a/README +++ b/README @@ -1202,8 +1202,10 @@ DATA FILTERS TRACK - The track filter is a tool for manipulating track lists. The - following options are available: + ( !!! This filter always drops empty tracks !!! ) + + The track filter is a tool for manipulating track lists. + The following options are available: TITLE @@ -1216,7 +1218,38 @@ DATA FILTERS -i gpx -f in.gpx \ -x track,pack,split,title="ACTIVE LOG-%D" \ -o gpx -F out.gpx PACK + + MOVE + + Change the time of all trackpoints. This is useful if + your track has moved by one or more hours through a + time zone problem. The following example will shift + your track to be one hour later. + gpsbabel -t \ + -i gpx -f in.gpx \ + -x track,move=+1h,pack,title="ACTIVE LOG" \ + -o gpx -F out.gpx + + START / STOP + + Filter tracks against time borders. All points outside + this range will be dropped. The date-time paramters + have to be in form of YYYYMMDDHHMMSS; but you may specify + only the most significant portion represented in the the + leftmost fields. See the example, where the time is + specified only through the hour. + + If you only want to get a track mapped on 20 july 2005 from + 10 am to 6pm, you should use this: + + gpsbabel -t \ + -i gpx -f in.gpx \ + -x track,start=2005072010,stop=2005072018 \ + -o gpx -F out.gpx + + PACK + With this default option all tracks from input will be packed into one track. If tracks overlaps in time, the filter stops working. To pack all the tracks together diff --git a/internal_styles.c b/internal_styles.c index fd42f49b6..e588d914f 100644 --- a/internal_styles.c +++ b/internal_styles.c @@ -411,14 +411,13 @@ static char openoffice[] = "#\n" "#\n" -"DESCRIPTION Custom \"Everything\" Style\n" +"DESCRIPTION Tab delimitered csv useful for OpenOffice, Ploticus etc.\n" "# FILE LAYOUT DEFINITIIONS:\n" "#\n" "FIELD_DELIMITER TAB\n" "RECORD_DELIMITER NEWLINE\n" "BADCHARS TAB\n" -"FORMAT_TYPE INTERNAL\n" "#\n" "# HEADER STUFF:\n" diff --git a/pathaway.c b/pathaway.c index 92580d86d..17dc0ac14 100644 --- a/pathaway.c +++ b/pathaway.c @@ -539,8 +539,7 @@ static void ppdb_write_wpt(const waypoint *wpt) static int ct; struct tm tm; - buff = xmalloc(REC_SIZE); - memset(buff, 0, REC_SIZE); + buff = xcalloc(REC_SIZE, 1); if (wpt->latitude < 0) latdir = 'S'; @@ -645,8 +644,7 @@ static void ppdb_write(void) if (global_opts.objective != wptdata) /* Waypoint target do not need appinfo block */ { - appinfo = xmalloc(PPDB_APPINFO_SIZE); - memset(appinfo, 0, PPDB_APPINFO_SIZE); + appinfo = xcalloc(PPDB_APPINFO_SIZE, 1); pdb_out->appinfo = (void *)appinfo; pdb_out->appinfo_len = PPDB_APPINFO_SIZE; diff --git a/trackfilter.c b/trackfilter.c index 8af2d2512..4257dfa40 100644 --- a/trackfilter.c +++ b/trackfilter.c @@ -1,4 +1,5 @@ /* + Track manipulation filter Copyright (C) 2005 Olaf Klein, o.b.klein@t-online.de @@ -21,32 +22,51 @@ /* 2005-07-20: implemented interval option from Etienne Tasse + 2005-07-26: implemented range option */ #include #include +#include #include "defs.h" +#include "strptime.h" -#define MYNAME "tracks" +#define MYNAME "trackfilter" #define TRACKFILTER_PACK_OPTION "pack" #define TRACKFILTER_SPLIT_OPTION "split" #define TRACKFILTER_TITLE_OPTION "title" +#define TRACKFILTER_MERGE_OPTION "merge" +#define TRACKFILTER_STOP_OPTION "stop" +#define TRACKFILTER_START_OPTION "start" +#define TRACKFILTER_MOVE_OPTION "move" #undef TRACKF_DBG +static char *opt_merge = NULL; static char *opt_pack = NULL; static char *opt_split = NULL; +static char *opt_move = NULL; static char *opt_title = NULL; +static char *opt_start = NULL; +static char *opt_stop = NULL; static arglist_t trackfilter_args[] = { - {TRACKFILTER_PACK_OPTION, &opt_pack, "Pack all tracks into one", - NULL, ARGTYPE_BOOL}, - {TRACKFILTER_SPLIT_OPTION, &opt_split, "Split track by date or by time interval (see README)", - NULL, ARGTYPE_STRING}, - {TRACKFILTER_TITLE_OPTION, &opt_title, "Basic title for new track(s)", - NULL, ARGTYPE_STRING}, + {TRACKFILTER_MOVE_OPTION, &opt_move, + "Correct trackpoint timestamps by a delta", NULL, ARGTYPE_STRING}, + {TRACKFILTER_PACK_OPTION, &opt_pack, + "Pack all tracks into one", NULL, ARGTYPE_BOOL}, + {TRACKFILTER_SPLIT_OPTION, &opt_split, + "Split track by date or by time interval (see README)", NULL, ARGTYPE_STRING}, + {TRACKFILTER_MERGE_OPTION, &opt_merge, + "Merge multiple tracks for the same way", NULL, ARGTYPE_STRING | ARGTYPE_HIDDEN}, + {TRACKFILTER_START_OPTION, &opt_start, + "Use only track points after this timestamp", NULL, ARGTYPE_INT}, + {TRACKFILTER_STOP_OPTION, &opt_stop, + "Use only track points before this timestamp", NULL, ARGTYPE_INT}, + {TRACKFILTER_TITLE_OPTION, &opt_title, + "Basic title for new track(s)", NULL, ARGTYPE_STRING}, {0, 0, 0, 0, 0} }; @@ -60,9 +80,12 @@ typedef struct trkflt_s static trkflt_t *track_list = NULL; static int track_ct = 0; +static int track_pts = 0; static int opt_interval = 0; -/*- dummy callbacks for track_disp_all ---------------------------------------------------*/ +/******************************************************************************* +* dummy callbacks for track_disp_all +*******************************************************************************/ static void trackfilter_noop_w(const waypoint *w) @@ -74,10 +97,62 @@ trackfilter_noop_t(const route_head *h) { } -/*----------------------------------------------------------------------------------------*/ +/******************************************************************************* +* helpers +*******************************************************************************/ + +int +trackfilter_opt_count(void) +{ + int res = 0; + arglist_t *a = trackfilter_args; + + while (a->argstring) + { + if (*a->argval != NULL) res++; + a++; + } + return res; +} + +int +trackfilter_parse_time_opt(const char *arg) +{ + time_t t0, t1; + int sign = 1; + char *cin = (char *)arg; + char c; + + t0 = t1 = 0; + + while ((c = *cin++)) + { + time_t seconds; + + if (c >= '0' && c <= '9') + { + t1 = (t1 * 10) + (c - '0'); + continue; + } + switch(tolower(c)) + { + case 'd': seconds = (24 * 60 * 60); break; + case 'h': seconds = (60 * 60); break; + case 'm': seconds = 60; break; + case 's': seconds = 1; break; + case '+': sign = +1; continue; + case '-': sign = -1; continue; + default: fatal(MYNAME "-time: invalid character in time option!\n"); + } + t0 += (t1 * seconds); + t1 = 0; + } + t0 += t1; + return t0 * sign; +} static int -trackfilter_qsort_cb(const void *a, const void *b) +trackfilter_init_qsort_cb(const void *a, const void *b) { const trkflt_t *ra = a; const trkflt_t *rb = b; @@ -85,76 +160,61 @@ trackfilter_qsort_cb(const void *a, const void *b) return ra->first_time - rb->first_time; } -/*----------------------------------------------------------------------------------------*/ +static int +trackfilter_merge_qsort_cb(const void *a, const void *b) +{ + const waypoint *wa = *(waypoint **)a; + const waypoint *wb = *(waypoint **)b; + + return wa->creation_time - wb->creation_time; +} static void -trackfilter_fill_track_list_cb(const route_head *trk) /* callback for track_disp_all */ +trackfilter_fill_track_list_cb(const route_head *track) /* callback for track_disp_all */ { int i; waypoint *wpt, *prev; queue *elem, *tmp; - track_list[track_ct].track = (route_head *)trk; - + if (track->rte_waypt_ct == 0) + { + track_del_head(track); + return; + } + + track_list[track_ct].track = (route_head *)track; + i = 0; prev = NULL; - QUEUE_FOR_EACH((queue *)&trk->waypoint_list, elem, tmp) + QUEUE_FOR_EACH((queue *)&track->waypoint_list, elem, tmp) { + track_pts++; + wpt = (waypoint *)elem; if (wpt->creation_time == 0) - fatal(MYNAME ": Found track point without time!\n"); + fatal(MYNAME "-init: Found track point without time!\n"); i++; if (i == 1) track_list[track_ct].first_time = wpt->creation_time; else - if (i == trk->rte_waypt_ct) + if (i == track->rte_waypt_ct) track_list[track_ct].last_time = wpt->creation_time; if ((prev != NULL) && (prev->creation_time > wpt->creation_time)) - fatal(MYNAME ": Track points bad ordered (timestamp)!\n"); - prev = wpt; - } - track_ct++; -} - -/*- global callbacks ---------------------------------------------------------------------*/ - -static void -trackfilter_init(const char *args) -{ - int i, j; - int count = track_count(); - trkflt_t prev; - - if (count > 0) - { - track_list = (trkflt_t *) xcalloc(count, sizeof(*track_list)); - - /* check all tracks for time and order */ - - track_ct = 0; - track_disp_all(trackfilter_fill_track_list_cb, trackfilter_noop_t, trackfilter_noop_w); - qsort(track_list, track_ct, sizeof(*track_list), trackfilter_qsort_cb); - - for (i=1, j=0; i= track_list[i].first_time) fatal(MYNAME " Tracks overlaps in time!\n"); + if (opt_merge == NULL) + fatal(MYNAME "-init: Track points badly ordered (timestamp)!\n"); } + prev = wpt; } + track_ct++; } -static void -trackfilter_deinit(void) -{ - if (track_list != NULL) - { - xfree(track_list); - track_list = NULL; - } -} +/******************************************************************************* +* track title producers +*******************************************************************************/ void trackfilter_split_init_rte_name(route_head *track, const time_t time) @@ -191,91 +251,173 @@ trackfilter_split_init_rte_name(route_head *track, const time_t time) track->rte_name = xstrdup(buff); } -/******************************************************************************************* -* -* option "pack" (default) -* -*******************************************************************************************/ - void -trackfilter_pack_init_rte_name(route_head *track, const time_t time) +trackfilter_pack_init_rte_name(route_head *track, const time_t default_time) { - char tbuff[128]; - struct tm tm; - - tm = *localtime(&time); + char buff[128]; - if ((opt_title != NULL) && (strlen(opt_title) > 0)) + if (strchr(opt_title, '%') != NULL) { - if (strchr(opt_title, '%') != NULL) - strftime(tbuff, sizeof(tbuff), opt_title, &tm); + struct tm tm; + waypoint *wpt; + + if (track->rte_waypt_ct == 0) + { + tm = *localtime(&default_time); + } else - strncpy(tbuff, opt_title, sizeof(tbuff)); + { + wpt = (waypoint *) QUEUE_FIRST((queue *)&track->waypoint_list); + tm = *localtime(&wpt->creation_time); + } + strftime(buff, sizeof(buff), opt_title, &tm); + } + else + strncpy(buff, opt_title, sizeof(buff)); - if (track->rte_name != NULL) xfree(track->rte_name); - track->rte_name = xstrdup(tbuff); + if (track->rte_name != NULL) + xfree(track->rte_name); + track->rte_name = xstrdup(buff); +} + +/******************************************************************************* +* option "title" +*******************************************************************************/ + +void +trackfilter_title(void) +{ + int i; + + if (opt_title == NULL) return; + + if (strlen(opt_title) == 0) { + fatal(MYNAME "-title: Missing your title!\n"); + } + for (i = 0; i < track_ct; i++) + { + route_head *track = track_list[i].track; + trackfilter_pack_init_rte_name(track, 0); } } -static void +/******************************************************************************* +* option "pack" (default) +*******************************************************************************/ + +void trackfilter_pack(void) { - int i, j, ct; - route_head *master, *curr; - queue *elem, *tmp; - waypoint *wpt; - waypoint **buff; + int i, j; + trkflt_t prev; + route_head *master; + + for (i = 1, j = 0; i < track_ct; i++, j++) + { + prev = track_list[j]; + if (prev.last_time >= track_list[i].first_time) + fatal(MYNAME "-pack: Tracks overlap in time!\n"); + } /* we fill up the first track by all other track points */ master = track_list[0].track; - - /* at this point we cannot set a new title, because track 0 - can be an empty track. If the title option is set, - we do this as final step in here - */ - for (i=1; iwaypoint_list, elem, tmp) + { + waypoint *wpt = (waypoint *)elem; + route_add_wpt(master, waypt_dupe(wpt)); + } + track_del_head(curr); + track_list[i].track = NULL; + } + track_ct = 1; +} + +/******************************************************************************* +* "hidden" option "merge" +*******************************************************************************/ +/* + MERGE - ct = curr->rte_waypt_ct; - buff = (waypoint **)xcalloc(ct, sizeof(*buff)); + Merge puts all track points into one single track and + sort them by time. Points with identical time stamp + will be dropped !!! - j = 0; - QUEUE_FOR_EACH((queue *)&curr->waypoint_list, elem, tmp) + If you want to merge tracks from different devices + but from same trip, use this: + + gpsbabel -t \ + -i gpx -f john.gpx \ + -i gpx -f doe.gpx \ + -x track,merge,title="COMBINED LOG" \ + -o gpx -F john_doe.gpx +*/ + +void +trackfilter_merge(void) +{ + int i, j, dropped; + + queue *elem, *tmp; + waypoint **buff; + waypoint *prev, *wpt; + route_head *master = track_list[0].track; + + if (track_pts < 1) return; + + buff = xcalloc(track_pts, sizeof(*buff)); + + j = 0; + for (i = 0; i < track_ct; i++) /* put all points into temp buffer */ + { + route_head *track = track_list[i].track; + QUEUE_FOR_EACH((queue *)&track->waypoint_list, elem, tmp) { wpt = (waypoint *)elem; - buff[j] = wpt; - j++; + buff[j++] = waypt_dupe(wpt); + route_del_wpt(track, wpt); } - - for (j=0; j 0 */ + track_del_head(track); + } + track_ct = 1; + + qsort(buff, track_pts, sizeof(*buff), trackfilter_merge_qsort_cb); + + dropped = 0; + prev = NULL; + + for (i = 0; i < track_pts; i++) + { + wpt = buff[i]; + if ((prev == NULL) || (prev->creation_time != wpt->creation_time)) { - wpt = waypt_dupe(buff[j]); - route_del_wpt(curr, buff[j]); route_add_wpt(master, wpt); + prev = wpt; + } + else + { + waypt_free(wpt); + dropped++; } - - xfree(buff); - - track_del_head(curr); } + xfree(buff); - if ((opt_split == NULL) && (master->rte_waypt_ct > 0)) - { - wpt = (waypoint *) QUEUE_FIRST((queue *)&master->waypoint_list); - trackfilter_pack_init_rte_name(master, wpt->creation_time); - } + if (global_opts.verbose_status > 0) + printf(MYNAME "-merge: %d track point(s) merged, %d dropped.\n", track_pts - dropped, dropped); } -/******************************************************************************************* -* +/******************************************************************************* * option "split" -* -*******************************************************************************************/ +*******************************************************************************/ -static void +void trackfilter_split(void) { route_head *curr; @@ -315,7 +457,7 @@ trackfilter_split(void) if (i == 0) { /* test reverse order */ - i = sscanf(opt_split,"%c%f", &interval, &dhms); + i = sscanf(opt_split,"%c%f", &dhms, &interval); } if ((i != 2) || (interval <= 0)) { @@ -407,31 +549,217 @@ trackfilter_split(void) xfree(buff); } -/******************************************************************************************/ +/******************************************************************************* +* option "move" +*******************************************************************************/ + +void +trackfilter_move(void) +{ + int i; + queue *elem, *tmp; + waypoint *wpt; + time_t delta; + + delta = trackfilter_parse_time_opt(opt_move); + if (delta == 0) return; + + for (i = 0; i < track_ct; i++) + { + route_head *track = track_list[i].track; + QUEUE_FOR_EACH((queue *)&track->waypoint_list, elem, tmp) + { + wpt = (waypoint *)elem; + wpt->creation_time += delta; + } + track_list[i].first_time += delta; + track_list[i].last_time += delta; + } +} + +/******************************************************************************* +* option: "start" / "stop" +*******************************************************************************/ + +time_t +trackfilter_range_check(const char *timestr) +{ + int i; + char fmt[20]; + char c; + char *cin; + struct tm time; + + + i = 0; + strncpy(fmt, "00000101000000", sizeof(fmt)); + cin = (char *)timestr; + + while ((c = *cin++)) + { + if (fmt[i] == '\0') fatal(MYNAME "-range: parameter too long \"%s\"!\n", timestr); + if (isdigit(c) == 0) fatal(MYNAME "-range: invalid character \"%c\"!\n", c); + fmt[i++] = c; + } + cin = strptime(fmt, "%Y%m%d%H%M%S", &time); + if ((cin != NULL) && (*cin != '\0')) + fatal(MYNAME "-range-check: Invalid time stamp (stopped at %s of %s)!\n", cin, fmt); + + return mkgmtime(&time); +} + +int +trackfilter_range(void) /* returns number of track points left after filtering */ +{ + time_t start, stop; + queue *elem, *tmp; + int i, dropped; + + if (opt_start != 0) + start = trackfilter_range_check(opt_start); + else + start = 0; + + if (opt_stop != 0) + stop = trackfilter_range_check(opt_stop); + else + stop = (unsigned long)-1; + + dropped = 0; + + for (i = 0; i < track_ct; i++) + { + route_head *track = track_list[i].track; + + QUEUE_FOR_EACH((queue *)&track->waypoint_list, elem, tmp) + { + waypoint *wpt = (waypoint *)elem; + + if ((wpt->creation_time < start) || (wpt->creation_time > stop)) + { + route_del_wpt(track, wpt); + dropped++; + } + } + + if (track->rte_waypt_ct == 0) + { + track_del_head(track); + track_list[i].track = NULL; + } + } + + if ((track_pts > 0) && (dropped == track_pts)) + warning(MYNAME "-range: All %d track points have been dropped!\n", track_pts); + + return track_pts - dropped; +} + +/******************************************************************************* +* global cb's +*******************************************************************************/ + +static void +trackfilter_init(const char *args) +{ + + int count = track_count(); + + track_ct = 0; + track_pts = 0; + + if (count > 0) + { + track_list = (trkflt_t *) xcalloc(count, sizeof(*track_list)); + + /* check all tracks for time and order (except merging) */ + + track_disp_all(trackfilter_fill_track_list_cb, trackfilter_noop_t, trackfilter_noop_w); + qsort(track_list, track_ct, sizeof(*track_list), trackfilter_init_qsort_cb); + } +} + +static void +trackfilter_deinit(void) +{ + if (track_list != NULL) + { + xfree(track_list); + track_list = NULL; + } + track_ct = 0; + track_pts = 0; +} + +/******************************************************************************* +* trackfilter_process: called from gpsbabel central engine +*******************************************************************************/ static void trackfilter_process(void) { - if (track_ct == 0) return; + int opts, something_done; + + if (track_ct == 0) return; /* no track(s), no fun */ + + opts = trackfilter_opt_count(); + if (opts == 0) opts = -1; /* flag for do "pack" by default */ - if (opt_pack == NULL && opt_split == NULL) + if (opt_move != NULL) /* Correct timestamps before any other op */ { - trackfilter_pack(); - return; + trackfilter_move(); + if (--opts == 0) return; } - if (opt_pack != 0 && track_ct > 0) + if ((opt_stop != NULL) || (opt_start != NULL)) { - trackfilter_pack(); - trackfilter_deinit(); + if (opt_start != NULL) opts--; + if (opt_stop != NULL) opts--; + + trackfilter_range(); + + if (opts == 0) return; + + trackfilter_deinit(); /* reinitialize */ trackfilter_init(NULL); + + } + + if (opt_title != NULL) + { + if (--opts == 0) + { + trackfilter_title(); + return; + } + } + + something_done = 0; + + if ((opt_pack != NULL) || (opts == -1)) /* call our default option */ + { + trackfilter_pack(); + something_done = 1; } - if (opt_split != 0 && track_ct > 0) + else if (opt_merge != NULL) { - if (track_ct > 1) fatal(MYNAME ": Cannot split more than one track, please pack before!\n"); + trackfilter_merge(); + something_done = 1; + } + + if ((something_done == 1) && (--opts <= 0)) + { + if (opt_title != NULL) + trackfilter_title(); + return; + } + + if (opt_split != NULL) + { + if (track_ct > 1) + fatal(MYNAME "-split: Cannot split more than one track, please pack (or merge) before!\n"); + trackfilter_split(); - trackfilter_deinit(); - trackfilter_init(NULL); } } @@ -444,3 +772,5 @@ filter_vecs_t trackfilter_vecs = { NULL, trackfilter_args }; + +/******************************************************************************************/ -- 2.30.2